package com.lvhx.springboot.base;

import org.springframework.util.Assert;

/**
 * 加载聚合的抽象类
 * 里面包含一个内部类，用来作为保存聚合的入口
 *
 * @param <T>
 */
public abstract class AbstractRepository<T extends AggregateRoot> implements Repository<T> {

    // 聚合类型
    private final Class<T> aggregateType;
    private final SimpleSaveAggregateCallback saveAggregateCallback = new SimpleSaveAggregateCallback();

    @Override
    public T load(Object aggregateIdentifier, Long expectedVersion, boolean lockYn) {
        T aggregate = null;

        if (CurrentUnitOfWork.isStarted()) {
            aggregate = CurrentUnitOfWork.get().getAggregate(aggregateType, aggregateIdentifier);
        }

        if (aggregate == null) {
            aggregate = doLoad(aggregateIdentifier, expectedVersion, lockYn);

            // 将加载的聚合，放入当前工作单元，后面更新聚合时，会从
            if (CurrentUnitOfWork.isStarted()) {

                // 校验聚合版本号
                validateOnLoad(aggregate, expectedVersion);

                if (CurrentUnitOfWork.isStarted()) {
                    return CurrentUnitOfWork.get().registerAggregate(aggregate, saveAggregateCallback);
                }
            }

        }
        return aggregate;
    }

    protected void validateOnLoad(T aggregate, Long expectedVersion) {
        if (expectedVersion != null && aggregate.getVersion() != null
                && !expectedVersion.equals(aggregate.getVersion())) {
            throw new RuntimeException("聚合版本号不正确！");
        }
    }

    @Override
    public T load(Object aggregateIdentifier) {

        return load(aggregateIdentifier, null, true);
    }

    @Override
    public T loadWithoutLock(Object aggregateIdentifier) {
        return null;
    }

    protected AbstractRepository(Class<T> aggregateType) {
        Assert.notNull(aggregateType, "aggregateType may not be null");
        this.aggregateType = aggregateType;
    }

    protected abstract T doLoad(Object aggregateIdentifier, Long expectedVersion, boolean lockYn);

    protected abstract void doSave(T aggregate);

    protected void postSave(T aggregate) {

    }

    /**
     * 保存聚合的实体类
     * 是加载聚合抽象类的内部类
     */
    private class SimpleSaveAggregateCallback implements SaveAggregateCallback<T> {
        @Override
        public void save(final T aggregate) {
            doSave(aggregate);
            postSave(aggregate);
        }
    }
}
